#ifndef _CONTROLLER_H_
#define _CONTROLLER_H_

#include "../define/define.h"
#include "../util/lock.h"
#include "../util/log.h"

#define min(a,b) ((a < b)? a : b)
#define max(a,b) ((a > b)? a : b)

const float define_rate = 85.0f;

class controller
{
public:
   controller()
   {
	    m_log = new logfile("controller");
	    func_lock locker;
		m_prev_rate = 0.0f;
		m_prev_dval = 0.0f;

		m_pval = 0.0f;
		m_dval = 0.0f;
		m_ival = 0.0f;

		m_tick = 0;
   }

   bool run(uint32 tick, float rate, uint16* pack_count,uint16* delay)
   {
	   func_lock locker;
	   if(m_tick != 0)
	   {
		   if(tick - m_tick <  200)
		      return false;
	   }
	   
	   m_tick = tick;

	   if(rate < 1.0f)
		   rate = 1.0f;
    
	   m_pval = define_rate / rate;
	   m_ival = 1.2f * (rate - define_rate) + 0.8f * m_ival;

	   if(m_prev_rate < 1.0f)
		   m_prev_rate = 1.0f;

	   m_dval = rate / m_prev_rate - m_prev_dval;

	   m_pval = min(m_pval,1.0f);
	   m_ival = min(m_ival,100.0f);
       m_ival = max(m_ival,-100.0f);
	   m_dval = min(m_dval,1.0f);
	   m_dval = max(m_dval,-1.0f);

	   float factor = 0.0f;

	   factor = 1.0f + (0.0325f * m_pval * 100.0f + 0.5175f *
		  m_ival + 0.45f * m_dval * 100.0f) / 100.0f;

	   if(m_dval < 0.0f)
		   factor = 1.0f + (0.07f * m_pval * 100.0f + 0.23f * m_ival
		      + 0.70f * m_dval * 100.0f) / 100.0f;

     
	   if (factor < 0.1f)
			factor = 0.1f;

	   	if (factor > 1.0f)
		{
			if (*delay > 2)
				*delay = *delay *  (factor - 1.0f) ;
			else
				*pack_count = *pack_count * factor;
		}
		
		if(factor <= 1.0f)
		{
			if (*pack_count > 32)
				*delay = *delay * (1.3f - factor);
			else
				*pack_count = *pack_count * factor;
		}

		m_prev_dval = rate / m_prev_rate;
		m_prev_rate = rate;

		*delay = min(*delay, 30);
		*delay = max(*delay, 10);
		*pack_count  = max(*pack_count, 8);
		*pack_count  = min(*pack_count, 32);

	    /*char tt[1024] ={0};
        sprintf(tt,"this=%x,m_prev_rate=%f,m_prev_dval=%f,factor=%f,pack_count=%d,delay=%d,m_pval=%f,m_ival=%f,m_dval=%f,rate=%f",
                   this,m_prev_rate,m_prev_dval,factor,*pack_count,*delay,m_pval,m_ival,m_dval,rate);
        m_log->WriteTrace(tt);*/

		return true;
   }

private:
	
   float m_prev_rate;
   float m_prev_dval;

   float m_pval;
   float m_dval;
   float m_ival;

   uint32 m_tick;

   logfile*  m_log;	
};
#endif